import OSS from 'ali-oss';
import { isTrue, throttle } from './tools';
import { Func } from '@/store/modules/basicData';
import { isNil } from 'ramda';
let getTemporaryCredentialsFunc: Func

export function isFileSizeExceeding50MB(file: XYFile) {
	// 100 MB 转换为字节
	const maxSize = 50 * 1024 * 1024; // 100 MB in bytes

	// 比较文件大小
	return file.size > maxSize;
}
export interface XYFile extends File {
	uid?: string | number
}
export interface OssData {
	filename?: string
	name?: string
	url?: string
	byte?: string
	type?: string
}
/** https://help.aliyun.com/zh/oss/developer-reference/initialization-10?spm=a2c4g.11186623.0.0.50244c204fDa3C */
export interface OssPolicyDto {
	accessKey: string
	policy: string
	signature: string
	path: string
	host: string
	expirationDateTime: string
	minSize: number
	maxSize: number
}
class aliOss {
	private timeout = 5 * 60 * 1000
	private client: OSS | undefined
	private endpoint = ''
	private accessKeyId = null
	private expirationDateTime = new Date()
	constructor() {
		// this.init()
	}
	async init() {
		if (isNil(getTemporaryCredentialsFunc)) {
			// 防抖
			getTemporaryCredentialsFunc = throttle(API.server.upload.getTemporaryCredentials.request)
		}
		const { success, data } = await API.server.upload.getTemporaryCredentials.request({})
		if (success) {
			this.expirationDateTime = new Date()
			/** 设置过期时间 */
			this.expirationDateTime.setSeconds(this.expirationDateTime.getSeconds() + 2000);
			this.accessKeyId = data.accessKeyId
			this.endpoint = data.endpoint
			this.client = new OSS({
				cname: true,
				endpoint: data.endpoint,
				accessKeyId: data.accessKeyId,
				accessKeySecret: data.accessKeySecret,
				bucket: data.bucket,
				timeout: this.timeout,
				stsToken: data.securityToken,
				refreshSTSToken: async () => {
					return {
						accessKeyId: data.accessKeyId as string,
						accessKeySecret: data.accessKeySecret as string,
						stsToken: data.securityToken as string,
					}
				}
			});
		}

	}
	async put(folder: string, file: XYFile, extension: string) {
		return await (this.client as OSS).put(isTrue(folder) ? `${folder}/${file.uid}.${extension}` : `${file.uid}.${extension}`, file);
	}
	/**
	 * 普通上传
	 * @param file 上传文件
	 * @param folder 上传文件夹路径
	 * @returns 
	 */
	uploadOSS(file: XYFile, folder?: string, progress?: ((...args: any[]) => any)): Promise<OssData> {
		return new Promise(async (resolve, reject) => {
			try {
				// 判断当前时间是否大于过期时间
				if (new Date().getTime() >= this.expirationDateTime.getTime() || !isTrue(this.accessKeyId)) {
					await this.init()
				}
				const extension = file.name.split('.').pop()?.toLowerCase();
				if (isFileSizeExceeding50MB(file)) {
					const result = await this.multipartUpload(folder as string, file, extension as string, progress as ((...args: any[]) => any))
					resolve({
						filename: result.name,
						url: result.url,
					} as OssData)
				} else {
					const result = await this.put(folder as string, file, extension as string)
					resolve({
						filename: result.name,
						url: result.url,
					} as OssData)
				}

			} catch (error: any) {
				reject(error.message)
				console.log(error.message);
			}
		})
	}
	async multipartUpload(folder: string, file: XYFile, extension: string, progress: ((...args: any[]) => any)) {
		const name = isTrue(folder) ? `${folder}/${file.uid}.${extension}` : `${file.uid}.${extension}`
		await (this.client as OSS).multipartUpload(name, file, {
			// 设置并发上传的分片数量。
			parallel: 4,
			// 设置分片大小。默认值为1 MB，最小值为100 KB。
			partSize: 1024 * 1024,
			progress,
		})
		return {
			name,
			url: `${this.endpoint}/${name}`,
		}
	}
	async removeOSS(filename: string) {
		try {
			// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
			const result = await this.client?.delete(filename);
			return {
				success: true,
				message: '删除成功'
			}
		} catch (error) {
			console.log(error);
			return {
				success: false,
				message: error
			}
		}
	}
}
export const AilOSS = new aliOss()
